package com.zhaoqi.hr.service;

import com.zhaoqi.hr.dto.request.JobApplicationRequest;
import com.zhaoqi.hr.dto.request.JobPostingRequest;
import com.zhaoqi.hr.dto.response.JobApplicationResponse;
import com.zhaoqi.hr.dto.response.JobPostingResponse;
import com.zhaoqi.hr.dto.response.EmployerProfileResponse;
import com.zhaoqi.hr.entity.EmployerProfile;
import com.zhaoqi.hr.entity.JobApplication;
import com.zhaoqi.hr.entity.JobPosting;
import com.zhaoqi.hr.entity.User;
import com.zhaoqi.hr.entity.WorkerProfile;
import com.zhaoqi.hr.repository.EmployerProfileRepository;
import com.zhaoqi.hr.repository.WorkerProfileRepository;
import com.zhaoqi.hr.repository.JobApplicationRepository;
import com.zhaoqi.hr.repository.JobPostingRepository;
import com.zhaoqi.hr.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 岗位服务
 */
@Service
public class JobService {

    private static final Logger log = LoggerFactory.getLogger(JobService.class);

    @Autowired
    private JobPostingRepository jobPostingRepository;
    
    @Autowired
    private JobApplicationRepository jobApplicationRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private EmployerProfileRepository employerProfileRepository;
    
    @Autowired
    private WorkerProfileRepository workerProfileRepository;

    /**
     * 发布岗位
     */
    @Transactional
    public JobPostingResponse publishJob(Long employerId, JobPostingRequest request) {
        log.info("用户 {} 发布岗位: {}", employerId, request.getTitle());

        // 验证用户存在且为雇主
        User employer = userRepository.findById(employerId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        if (employer.getRole() != User.UserRole.EMPLOYER) {
            throw new RuntimeException("只有雇主可以发布岗位");
        }

        // 获取雇主Profile
        EmployerProfile employerProfile = employerProfileRepository.findByUserId(employerId)
                .orElseThrow(() -> new RuntimeException("雇主信息不存在"));

        // 创建岗位
        JobPosting jobPosting = new JobPosting();
        jobPosting.setEmployer(employerProfile);
        jobPosting.setTitle(request.getTitle());
        jobPosting.setDescription(request.getDescription());
        jobPosting.setJobType(request.getJobType());
        jobPosting.setLocation(request.getLocation());
        jobPosting.setSalary(request.getSalary());
        jobPosting.setSalaryType(request.getSalaryType());
        jobPosting.setRequiredCount(request.getRequiredCount());
        jobPosting.setStartTime(request.getStartTime());
        jobPosting.setEndTime(request.getEndTime());
        jobPosting.setSkillRequirements(request.getSkillRequirements());
        jobPosting.setOtherRequirements(request.getOtherRequirements());
        jobPosting.setContactInfo(request.getContactInfo());
        jobPosting.setStatus(JobPosting.JobStatus.ACTIVE);
        jobPosting.setCreatedAt(LocalDateTime.now());
        jobPosting.setUpdatedAt(LocalDateTime.now());

        jobPosting = jobPostingRepository.save(jobPosting);

        log.info("岗位发布成功，ID: {}", jobPosting.getId());
        return convertToJobPostingResponse(jobPosting);
    }

    /**
     * 获取岗位列表（分页）
     */
    public Page<JobPostingResponse> getJobPostings(Pageable pageable, JobPosting.JobStatus status, 
                                                   JobPosting.JobType jobType, String location) {
        Page<JobPosting> jobPostings;
        
        if (status != null && jobType != null && location != null) {
            jobPostings = jobPostingRepository.findByStatusAndJobTypeAndLocationContaining(
                    status, jobType, location, pageable);
        } else if (status != null) {
            jobPostings = jobPostingRepository.findByStatusOrderByCreatedAtDesc(status, pageable);
        } else {
            jobPostings = jobPostingRepository.findAllByOrderByCreatedAtDesc(pageable);
        }
        
        return jobPostings.map(this::convertToJobPostingResponse);
    }

    /**
     * 获取岗位详情
     */
    public JobPostingResponse getJobPostingById(Long jobId) {
        JobPosting jobPosting = jobPostingRepository.findById(jobId)
                .orElseThrow(() -> new RuntimeException("岗位不存在"));
        return convertToJobPostingResponse(jobPosting);
    }

    /**
     * 获取雇主发布的岗位列表
     */
    public List<JobPostingResponse> getEmployerJobPostings(Long employerId) {
        List<JobPosting> jobPostings = jobPostingRepository.findByEmployer_User_IdOrderByCreatedAtDesc(employerId);
        return jobPostings.stream()
                .map(this::convertToJobPostingResponse)
                .collect(Collectors.toList());
    }

    /**
     * 申请岗位
     */
    @Transactional
    public JobApplicationResponse applyForJob(Long workerId, JobApplicationRequest request) {
        log.info("用户 {} 申请岗位 {}", workerId, request.getJobPostingId());

        // 验证用户存在且为劳动者
        User worker = userRepository.findById(workerId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        if (worker.getRole() != User.UserRole.WORKER) {
            throw new RuntimeException("只有劳动者可以申请岗位");
        }

        // 验证岗位存在且状态为活跃
        JobPosting jobPosting = jobPostingRepository.findById(request.getJobPostingId())
                .orElseThrow(() -> new RuntimeException("岗位不存在"));
        
        if (jobPosting.getStatus() != JobPosting.JobStatus.ACTIVE) {
            throw new RuntimeException("岗位已关闭，无法申请");
        }

        // 检查是否已申请过
        boolean alreadyApplied = jobApplicationRepository.existsByJobPosting_IdAndWorker_User_Id(
                request.getJobPostingId(), workerId);
        if (alreadyApplied) {
            throw new RuntimeException("您已申请过此岗位");
        }

        // 获取劳动者档案
        WorkerProfile workerProfile = workerProfileRepository.findByUserId(workerId)
                .orElseThrow(() -> new RuntimeException("劳动者档案不存在"));
        
        // 创建申请记录
        JobApplication application = new JobApplication();
        application.setJobPosting(jobPosting);
        application.setWorker(workerProfile);
        application.setApplicationNote(request.getApplicationNote());
        application.setExpectedSalary(request.getExpectedSalary());
        application.setPersonalAdvantage(request.getPersonalAdvantage());
        application.setStatus(JobApplication.ApplicationStatus.PENDING);
        application.setAppliedAt(LocalDateTime.now());
        application.setCreatedAt(LocalDateTime.now());
        application.setUpdatedAt(LocalDateTime.now());

        application = jobApplicationRepository.save(application);

        log.info("岗位申请成功，ID: {}", application.getId());
        return convertToJobApplicationResponse(application);
    }

    /**
     * 获取岗位申请列表（雇主查看）
     */
    public List<JobApplicationResponse> getJobApplications(Long employerId, Long jobPostingId) {
        // 验证岗位属于该雇主
        JobPosting jobPosting = jobPostingRepository.findById(jobPostingId)
                .orElseThrow(() -> new RuntimeException("岗位不存在"));
        
        if (!jobPosting.getEmployer().getUser().getId().equals(employerId)) {
            throw new RuntimeException("无权限查看此岗位的申请");
        }

        List<JobApplication> applications = jobApplicationRepository.findByJobPosting_IdOrderByAppliedAtDesc(jobPostingId);
        
        return applications.stream()
                .map(this::convertToJobApplicationResponse)
                .collect(Collectors.toList());
    }

    /**
     * 获取劳动者的申请列表
     */
    public List<JobApplicationResponse> getWorkerApplications(Long workerId) {
        List<JobApplication> applications = jobApplicationRepository.findByWorker_User_IdOrderByAppliedAtDesc(workerId);
        
        return applications.stream()
                .map(this::convertToJobApplicationResponse)
                .collect(Collectors.toList());
    }

    /**
     * 处理岗位申请（雇主操作）
     */
    @Transactional
    public JobApplicationResponse processApplication(Long employerId, Long applicationId, 
                                                   JobApplication.ApplicationStatus status, String reply) {
        log.info("雇主 {} 处理申请 {}, 状态: {}", employerId, applicationId, status);

        JobApplication application = jobApplicationRepository.findById(applicationId)
                .orElseThrow(() -> new RuntimeException("申请不存在"));

        // 验证权限
        JobPosting jobPosting = application.getJobPosting();
        if (jobPosting == null) {
            throw new RuntimeException("岗位不存在");
        }
        
        if (!jobPosting.getEmployer().getUser().getId().equals(employerId)) {
            throw new RuntimeException("无权限处理此申请");
        }

        if (application.getStatus() != JobApplication.ApplicationStatus.PENDING) {
            throw new RuntimeException("申请已处理，无法重复操作");
        }

        // 更新申请状态
        application.setStatus(status);
        application.setEmployerReply(reply);
        application.setProcessedAt(LocalDateTime.now());
        application.setUpdatedAt(LocalDateTime.now());

        application = jobApplicationRepository.save(application);

        log.info("申请处理完成，状态: {}", status);
        return convertToJobApplicationResponse(application);
    }

    /**
     * 更新岗位状态
     */
    @Transactional
    public JobPostingResponse updateJobStatus(Long employerId, Long jobId, JobPosting.JobStatus status) {
        JobPosting jobPosting = jobPostingRepository.findById(jobId)
                .orElseThrow(() -> new RuntimeException("岗位不存在"));
        
        if (!jobPosting.getEmployer().getUser().getId().equals(employerId)) {
            throw new RuntimeException("无权限修改此岗位");
        }

        jobPosting.setStatus(status);
        jobPosting.setUpdatedAt(LocalDateTime.now());
        
        jobPosting = jobPostingRepository.save(jobPosting);
        
        log.info("岗位状态更新成功，ID: {}, 状态: {}", jobId, status);
        return convertToJobPostingResponse(jobPosting);
    }

    /**
     * 转换为岗位响应DTO
     */
    private JobPostingResponse convertToJobPostingResponse(JobPosting jobPosting) {
        JobPostingResponse response = new JobPostingResponse(jobPosting);
        
        // 获取申请数量
        long applicationCount = jobApplicationRepository.countByJobPosting_Id(jobPosting.getId());
        response.setAppliedCount((int) applicationCount);

        return response;
    }

    /**
     * 转换为申请响应DTO
     */
    private JobApplicationResponse convertToJobApplicationResponse(JobApplication application) {
        JobApplicationResponse response = new JobApplicationResponse();
        response.setId(application.getId());
        response.setJobPostingId(application.getJobPosting() != null ? application.getJobPosting().getId() : null);
        response.setWorkerId(application.getWorker() != null ? application.getWorker().getUser().getId() : null);
        response.setApplicationNote(application.getApplicationNote());
        response.setExpectedSalary(application.getExpectedSalary());
        response.setPersonalAdvantage(application.getPersonalAdvantage());
        response.setStatus(application.getStatus());
        response.setEmployerReply(application.getEmployerReply());
        response.setAppliedAt(application.getAppliedAt());
        response.setProcessedAt(application.getProcessedAt());
        response.setCreatedAt(application.getCreatedAt());
        response.setUpdatedAt(application.getUpdatedAt());

        // 获取岗位标题
        if (application.getJobPosting() != null) {
            response.setJobTitle(application.getJobPosting().getTitle());
        }

        // 获取申请者信息
        if (application.getWorker() != null && application.getWorker().getUser() != null) {
            User worker = application.getWorker().getUser();
            response.setWorkerName(worker.getRealName());
            response.setWorkerPhone(worker.getPhone());
        }

        return response;
    }

    /**
     * 获取岗位管理列表（管理员专用）
     */
    @Transactional(readOnly = true)
    public Page<JobPostingResponse> getJobPostingsForAdmin(Pageable pageable, String status, String keyword) {
        Specification<JobPosting> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (status != null && !status.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("status"), JobPosting.JobStatus.valueOf(status)));
            }
            
            if (keyword != null && !keyword.trim().isEmpty()) {
                Predicate titlePredicate = criteriaBuilder.like(root.get("title"), "%" + keyword + "%");
                Predicate descriptionPredicate = criteriaBuilder.like(root.get("description"), "%" + keyword + "%");
                predicates.add(criteriaBuilder.or(titlePredicate, descriptionPredicate));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        Page<JobPosting> jobPage = jobPostingRepository.findAll(spec, pageable);
        return jobPage.map(this::convertToJobPostingResponse);
    }

    /**
     * 获取岗位申请管理列表（管理员专用）
     */
    public Page<JobApplicationResponse> getJobApplicationsForAdmin(Pageable pageable, String status) {
        Specification<JobApplication> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (status != null && !status.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("status"), JobApplication.ApplicationStatus.valueOf(status)));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        Page<JobApplication> applicationPage = jobApplicationRepository.findAll(spec, pageable);
        return applicationPage.map(this::convertToJobApplicationResponse);
    }

    /**
     * 删除岗位（管理员专用）
     */
    @Transactional
    public void deleteJob(Long jobId) {
        JobPosting job = jobPostingRepository.findById(jobId)
                .orElseThrow(() -> new RuntimeException("岗位不存在"));
        
        // 检查岗位状态，只有特定状态的岗位才能删除
        if (job.getStatus() == JobPosting.JobStatus.ACTIVE || 
            job.getStatus() == JobPosting.JobStatus.WORKER_ASSIGNED) {
            throw new RuntimeException("活跃状态或已分配劳动者的岗位不能删除");
        }
        
        jobPostingRepository.delete(job);
        log.info("岗位删除成功，岗位ID: {}", jobId);
    }

    /**
     * 人工撮合岗位和劳动者（管理员专用）
     */
    @Transactional
    public void manualMatchJob(Long jobId, List<Long> workerIds, String matchReason) {
        JobPosting job = jobPostingRepository.findById(jobId)
                .orElseThrow(() -> new RuntimeException("岗位不存在"));

        if (job.getStatus() != JobPosting.JobStatus.PUBLISHED) {
            throw new RuntimeException("只能撮合已发布的岗位");
        }

        for (Long workerId : workerIds) {
            // 检查是否已存在申请
            boolean applicationExists = jobApplicationRepository.existsByJobPosting_IdAndWorker_User_Id(jobId, workerId);
            if (applicationExists) {
                log.warn("劳动者 {} 已申请岗位 {}，跳过撮合", workerId, jobId);
                continue;
            }

            // 获取劳动者档案
            WorkerProfile workerProfile = workerProfileRepository.findByUserId(workerId)
                    .orElseThrow(() -> new RuntimeException("劳动者档案不存在: " + workerId));
            
            // 创建系统撮合申请
            JobApplication application = new JobApplication();
            application.setJobPosting(job);
            application.setWorker(workerProfile);
            application.setApplicationNote("系统人工撮合：" + (matchReason != null ? matchReason : "管理员推荐"));
            application.setExpectedSalary(job.getSalary().toString());
            application.setPersonalAdvantage("管理员推荐匹配");
            application.setStatus(JobApplication.ApplicationStatus.PENDING);
            application.setCreatedAt(LocalDateTime.now());
            application.setUpdatedAt(LocalDateTime.now());

            jobApplicationRepository.save(application);
            log.info("管理员撮合成功，岗位ID: {}, 劳动者ID: {}", jobId, workerId);
        }

        log.info("人工撮合完成，岗位ID: {}, 撮合劳动者数量: {}", jobId, workerIds.size());
    }

    /**
     * 管理员创建岗位
     */
    @Transactional
    public JobPostingResponse createJobByAdmin(JobPostingRequest request) {
        JobPosting job = new JobPosting();
        job.setTitle(request.getTitle());
        job.setDescription(request.getDescription());
        job.setJobType(request.getJobType());
        job.setLocation(request.getLocation());
        job.setSalary(request.getSalary());
        job.setSalaryType(request.getSalaryType());
        job.setRequiredCount(request.getRequiredCount());
        job.setStartTime(request.getStartTime());
        job.setEndTime(request.getEndTime());
        job.setSkillRequirements(request.getSkillRequirements());
        job.setOtherRequirements(request.getOtherRequirements());
        job.setContactInfo(request.getContactInfo());
        job.setCreatedAt(LocalDateTime.now());
        job.setUpdatedAt(LocalDateTime.now());

        // 设置用工方
        if (request.getEmployerId() != null) {
            EmployerProfile employer = employerProfileRepository.findById(request.getEmployerId())
                .orElseThrow(() -> new RuntimeException("用工方不存在"));
            job.setEmployer(employer);
        }

        // 设置劳动者关联和状态
        if (request.getAssignedWorkerId() != null) {
            WorkerProfile worker = workerProfileRepository.findById(request.getAssignedWorkerId())
                .orElseThrow(() -> new RuntimeException("劳动者不存在"));
            job.setAssignedWorkerId(request.getAssignedWorkerId());
            job.setAssignedAt(LocalDateTime.now());
            job.setStatus(JobPosting.JobStatus.WORKER_ASSIGNED); // 已分配劳动者
        } else {
            job.setStatus(JobPosting.JobStatus.PUBLISHED); // 已发布，等待申请
        }

        JobPosting savedJob = jobPostingRepository.save(job);
        log.info("管理员创建岗位成功: {}, 用工方: {}, 劳动者: {}", 
            savedJob.getTitle(), 
            savedJob.getEmployer() != null ? savedJob.getEmployer().getId() : "无",
            savedJob.getAssignedWorkerId() != null ? savedJob.getAssignedWorkerId() : "无");
        
        return new JobPostingResponse(savedJob);
    }
}
